﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using System.Threading.Tasks;
using BCCommon;
using BCEntity.MakeStaticPagingComponent.PageTemplate;
using Dapper;

namespace BCData.MakeStaticPagingComponent.PageTemplate
{
    /// <summary>
    /// 页面模板数据处理
    /// </summary>
    public class PageTemplateData : IPageTemplateData
    {
        private readonly IDatabaseContext databaseContext;
        private const string QUERY = @"SELECT PageTemplateId,PageName,PageCode,PageHtml,CreateTime,WebsiteTemplateId,PageHtmlPath,PageIndex,PageLevelCode,PageKeyword,PageDescription,PageDefine,
                                            (SELECT PageName FROM PageTemplate B WHERE PageCode=A.ParentPageCode AND B.WebsiteTemplateId=A.WebsiteTemplateId) AS ParentPageName,
                                            IsUsed,ParentPageCode,PageLevel,PageUrlName,IsSystem,IsContentPage,IsPagingListPage,PagingListServiceTag,PagingListServiceParams,SystemServiceListingId,UpdateTime,
                                            TotalPageCount,ListSize,CurrentlyPageNumber,ContentPageCode
                                        FROM PageTemplate A";
        private const string QUERY_CHILDREN_COUNT = @"SELECT PageTemplateId,PageName,PageCode,PageHtml,CreateTime,WebsiteTemplateId,PageHtmlPath,PageIndex,PageLevelCode,PageKeyword,PageDescription,PageDefine,
                                            IsUsed,ParentPageCode,PageLevel,PageUrlName,IsSystem,IsContentPage,IsPagingListPage,PagingListServiceTag,PagingListServiceParams,SystemServiceListingId,UpdateTime,
                                            TotalPageCount,ListSize,CurrentlyPageNumber,ContentPageCode,
                                            CASE WHEN (SELECT COUNT(1) FROM PageTemplate B WHERE ParentPageCode=A.PageCode)>0 THEN TRUE ELSE FALSE END AS IsParent
                                        FROM PageTemplate A";
        public PageTemplateData(IDatabaseContext databaseContext)
        {
            this.databaseContext=databaseContext;
        }

        public PageTemplateEntity Add(PageTemplateEntity pageTemplateEntity)
        {
            string sql = @"INSERT INTO PageTemplate(PageName,PageCode,PageHtml,PageDefine,WebsiteTemplateId,ParentPageCode,PageHtmlPath,PageIndex,PageLevelCode,PageKeyword,PageDescription,PageLevel,PageUrlName,IsContentPage,IsUsed,ContentPageCode,IsPagingListPage,PagingListServiceTag,PagingListServiceParams,SystemServiceListingId,ListSize)
                            VALUES(?PageName,?PageCode,?PageHtml,?PageDefine,?WebsiteTemplateId,?ParentPageCode,?PageHtmlPath,?PageIndex,?PageLevelCode,?PageKeyword,?PageDescription,?PageLevel,?PageUrlName,?IsContentPage,?IsUsed,?ContentPageCode,?IsPagingListPage,?PagingListServiceTag,?PagingListServiceParams,?SystemServiceListingId,?ListSize);";
            sql = string.Format("{0} {1} WHERE PageTemplateId=LAST_INSERT_ID();", sql, QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageName", pageTemplateEntity.PageName, DbType.AnsiString, size: 50);
            parameters.Add("?PageCode", pageTemplateEntity.PageCode, DbType.AnsiString, size: 50);
            parameters.Add("?PageHtml", pageTemplateEntity.PageHtml, DbType.String);
            parameters.Add("?PageDefine", pageTemplateEntity.PageDefine, DbType.String);
            parameters.Add("?WebsiteTemplateId", pageTemplateEntity.WebsiteTemplateId, DbType.Int32, size: 11);
            parameters.Add("?ParentPageCode", pageTemplateEntity.ParentPageCode, DbType.AnsiString, size: 50);
            parameters.Add("?PageHtmlPath", pageTemplateEntity.PageHtmlPath, DbType.AnsiString, size: 1000);
            parameters.Add("?PageIndex", pageTemplateEntity.PageIndex, DbType.Int32);
            parameters.Add("?PageLevelCode", pageTemplateEntity.PageLevelCode, DbType.AnsiString, size: 2000);
            parameters.Add("?PageKeyword", pageTemplateEntity.PageKeyword, DbType.AnsiString, size: 1000);
            parameters.Add("?PageDescription", pageTemplateEntity.PageDescription, DbType.AnsiString, size: 2000);
            parameters.Add("?PageLevel", pageTemplateEntity.PageLevel, DbType.Int32, size: 11);
            parameters.Add("?PageUrlName", pageTemplateEntity.PageUrlName, DbType.AnsiString, size: 50);
            parameters.Add("?IsContentPage", pageTemplateEntity.IsContentPage, DbType.Boolean);
            parameters.Add("?IsUsed", pageTemplateEntity.IsUsed, DbType.Boolean);
            parameters.Add("?ContentPageCode", pageTemplateEntity.ContentPageCode, DbType.AnsiString, size: 50);
            parameters.Add("?IsPagingListPage", pageTemplateEntity.IsPagingListPage, DbType.Boolean);
            parameters.Add("?PagingListServiceTag", pageTemplateEntity.PagingListServiceTag, DbType.String);
            parameters.Add("?PagingListServiceParams", pageTemplateEntity.PagingListServiceParams, DbType.String);
            parameters.Add("?SystemServiceListingId", pageTemplateEntity.SystemServiceListingId, DbType.Int32);
            parameters.Add("?ListSize", pageTemplateEntity.ListSize, DbType.Int32);
            return this.databaseContext.Master.QueryEntity<PageTemplateEntity>(sql,parameters, databaseContext.Transaction);
        }
        public bool CheckPageTemplateExists(string pageUrlName, int websiteTemplateId)
        {
            string sql = @"SELECT 1 FROM PageTemplate WHERE PageUrlName=?PageUrlName AND WebsiteTemplateId=?WebsiteTemplateId LIMIT 1;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageUrlName", pageUrlName, DbType.AnsiString, size: 50);
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameters);
            return result != null;
        }
        public bool CheckPageTemplateExists(string pageUrlName, int websiteTemplateId,long pageTemplateId)
        {
            string sql = @"SELECT 1 FROM PageTemplate WHERE PageUrlName=?PageUrlName AND WebsiteTemplateId=?WebsiteTemplateId AND PageTemplateId!=?PageTemplateId LIMIT 1;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageUrlName", pageUrlName, DbType.AnsiString, size: 50);
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            parameters.Add("?PageTemplateId", pageTemplateId, DbType.Int64, size: 20);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameters);
            return result != null;
        }

        public bool CheckPageTemplateExists(int websiteTemplateId, string pageCode)
        {
            string sql = @"SELECT 1 FROM PageTemplate WHERE PageCode=?PageCode AND WebsiteTemplateId=?WebsiteTemplateId LIMIT 1;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageCode", pageCode, DbType.AnsiString, size: 50);
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameters);
            return result != null;
        }
        public bool CheckPageTemplateExists(int websiteTemplateId, string pageCode, long pageTemplateId)
        {
            string sql = @"SELECT 1 FROM PageTemplate WHERE PageCode=?PageCode AND WebsiteTemplateId=?WebsiteTemplateId AND PageTemplateId!=?PageTemplateId LIMIT 1;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageCode", pageCode, DbType.AnsiString, size: 50);
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            parameters.Add("?PageTemplateId", pageTemplateId, DbType.Int64, size: 20);
            object result = this.databaseContext.Slave.ExecuteScalar(sql,parameters);
            return result != null;
        }
        public bool CheckPageTemplateExists(long pageTemplateId)
        {
            string sql = @"SELECT 1 FROM PageTemplate WHERE PageTemplateId=?PageTemplateId LIMIT 1;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageTemplateId", pageTemplateId, DbType.Int64);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameters);
            return result != null;
        }

        public bool CheckParentPageTemplateExists(int websiteTemplateId, string parentPageCode)
        {
            string sql = @"SELECT 1 FROM PageTemplate WHERE PageCode=?ParentPageCode AND WebsiteTemplateId=?WebsiteTemplateId LIMIT 1;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?ParentPageCode", parentPageCode, DbType.AnsiString, size: 50);
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameters);
            return result != null;
        }

        public bool CheckContentPageCodeExists(int websiteTemplateId, string ContentPageCode)
        {
            string sql = @"SELECT 1 FROM PageTemplate WHERE PageCode=?ContentPageCode AND WebsiteTemplateId=?WebsiteTemplateId LIMIT 1;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?ContentPageCode", ContentPageCode, DbType.AnsiString, size: 50);
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameters);
            return result != null;
        }

        public bool CheckPageCodeExists(string pageCode)
        {
            string sql = @"SELECT 1 FROM PageTemplate WHERE PageCode=?PageCode LIMIT 1;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageCode", pageCode, DbType.AnsiString);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameters);
            return result != null;
        }

        public PageTemplateEntity Get(string pageCode, int websiteTemplateId)
        {
            string sql = string.Format("{0} WHERE A.PageCode=?PageCode AND A.WebsiteTemplateId=?WebsiteTemplateId LIMIT 1;", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageCode", pageCode, DbType.AnsiString, size: 50);
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.AnsiString);
            return this.databaseContext.Slave.QueryEntity<PageTemplateEntity>(sql, parameters);
        }

        public PageTemplateEntity Get(long pageTemplateId)
        {
            string sql = string.Format("{0} WHERE A.PageTemplateId=?PageTemplateId LIMIT 1;", QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageTemplateId", pageTemplateId, DbType.Int64);
            return this.databaseContext.Slave.QueryEntity<PageTemplateEntity>(sql, parameters);
        }

        public IEnumerable<PageTemplateEntity> Get(string pageName, int websiteTemplateId, out int dataCount, bool? ascending, int index = 1, int size = 20)
        {
            List<string> wheres = new List<string>();
            DynamicParameters parameters = new DynamicParameters();

            wheres.Add("A.WebsiteTemplateId=?WebsiteTemplateId");
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            if (!string.IsNullOrWhiteSpace(pageName))
            {
                wheres.Add("A.PageName LIKE CONCAT('%',CONCAT(?PageName,'%'))");
                parameters.Add("?PageName", pageName, DbType.AnsiString);
            }
            else
            {
                wheres.Add("A.PageLevel=0");
            }
            string sql = string.Format(@"{0} {1} ORDER BY PageLevelCode {4} LIMIT {2},{3}; SELECT Count(1) FROM PageTemplate A {1}",
                 QUERY,
                 wheres.Count > 0 ? "WHERE " + string.Join(" AND ", wheres) : string.Empty,
                 (index == 0 ? 0 : index - 1) * size,
                 size,
                 ascending.HasValue && ascending.Value ? "ASC" : "DESC"
            );
            var result = this.databaseContext.Slave.QueryMultiple<PageTemplateEntity, int>(sql,parameters);

            dataCount = result.Item2;

            return result.Item1;
        }

        public IEnumerable<PageTemplateEntity> Get()
        {
            string sql = string.Format("{0} WHERE A.IsUsed=1", QUERY);
            return this.databaseContext.Slave.Query<PageTemplateEntity>(sql);
        }

        public PageTemplateEntity Update(PageTemplateEntity pageTemplateEntity)
        {
            string sql = @"UPDATE PageTemplate SET
                                PageName=?PageName,
                                PageCode=?PageCode,
                                PageHtml=?PageHtml,
                                PageDefine=?PageDefine,
                                WebsiteTemplateId=?WebsiteTemplateId,
                                ParentPageCode=?ParentPageCode,
                                PageHtmlPath=?PageHtmlPath,
                                PageIndex=?PageIndex,
                                PageLevelCode=?PageLevelCode,
                                PageKeyword=?PageKeyword,
                                PageDescription=?PageDescription,
                                PageLevel=?PageLevel,
                                PageUrlName=?PageUrlName,
                                IsUsed=?IsUsed,
                                ContentPageCode=?ContentPageCode,
                                IsContentPage=?IsContentPage,
                                IsPagingListPage=?IsPagingListPage,
                                PagingListServiceTag=?PagingListServiceTag,
                                PagingListServiceParams=?PagingListServiceParams,
                                SystemServiceListingId=?SystemServiceListingId,
                                ListSize=?ListSize,
                                TotalPageCount=?TotalPageCount,
                                CurrentlyPageNumber=?CurrentlyPageNumber
                            WHERE PageTemplateId=?PageTemplateId;";
            sql = string.Format("{0} {1} WHERE A.PageTemplateId=?PageTemplateId LIMIT 1;", sql, QUERY);
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageTemplateId", pageTemplateEntity.PageTemplateId, DbType.Int64);
            parameters.Add("?PageName", pageTemplateEntity.PageName, DbType.AnsiString, size: 50);
            parameters.Add("?PageCode", pageTemplateEntity.PageCode, DbType.AnsiString, size: 50);
            parameters.Add("?PageHtml", pageTemplateEntity.PageHtml, DbType.String);
            parameters.Add("?PageDefine", pageTemplateEntity.PageDefine, DbType.String);
            parameters.Add("?WebsiteTemplateId", pageTemplateEntity.WebsiteTemplateId, DbType.Int32, size: 11);
            parameters.Add("?ParentPageCode", pageTemplateEntity.ParentPageCode, DbType.AnsiString, size: 50);
            parameters.Add("?PageHtmlPath", pageTemplateEntity.PageHtmlPath, DbType.AnsiString, size: 1000);
            parameters.Add("?PageIndex", pageTemplateEntity.PageIndex, DbType.Int32, size: 11);
            parameters.Add("?PageLevelCode", pageTemplateEntity.PageLevelCode, DbType.AnsiString, size: 2000);
            parameters.Add("?PageKeyword", pageTemplateEntity.PageKeyword, DbType.AnsiString, size: 1000);
            parameters.Add("?PageDescription", pageTemplateEntity.PageDescription, DbType.AnsiString, size: 2000);
            parameters.Add("?PageLevel", pageTemplateEntity.PageLevel, DbType.Int32, size: 11);
            parameters.Add("?PageUrlName", pageTemplateEntity.PageUrlName, DbType.AnsiString, size: 50);
            parameters.Add("?IsUsed", pageTemplateEntity.IsUsed, DbType.Boolean);
            parameters.Add("?ContentPageCode", pageTemplateEntity.ContentPageCode, DbType.AnsiString, size: 50);
            parameters.Add("?IsContentPage", pageTemplateEntity.IsContentPage, DbType.Boolean);
            parameters.Add("?IsPagingListPage", pageTemplateEntity.IsPagingListPage, DbType.Boolean);
            parameters.Add("?PagingListServiceTag", pageTemplateEntity.PagingListServiceTag, DbType.String);
            parameters.Add("?PagingListServiceParams", pageTemplateEntity.PagingListServiceParams, DbType.String);
            parameters.Add("?SystemServiceListingId", pageTemplateEntity.SystemServiceListingId, DbType.Int32);
            parameters.Add("?ListSize", pageTemplateEntity.ListSize, DbType.Int32,size:11);
            parameters.Add("?TotalPageCount", pageTemplateEntity.TotalPageCount, DbType.Int32, size: 11);
            parameters.Add("?CurrentlyPageNumber", pageTemplateEntity.CurrentlyPageNumber, DbType.Int32, size: 11);
            
            return this.databaseContext.Master.QueryEntity<PageTemplateEntity>(sql,parameters, databaseContext.Transaction);
        }

        public bool UpdateWebsiteTemplateIsUsed(int websiteTemplateId)
        {
            string sql = @"UPDATE PageTemplate SET 
                                IsUsed=0;
                           UPDATE PageTemplate SET 
                                IsUsed=1
                           WHERE WebsiteTemplateId=?WebsiteTemplateId;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            int result = this.databaseContext.Master.Execute(sql, parameters, databaseContext.Transaction);
            return result > 0;
        }

        public bool CheckWebsiteTemplateIdExists(int websiteTemplateId)
        {
            string sql = @"SELECT 1 FROM PageTemplate WHERE WebsiteTemplateId=?WebsiteTemplateId LIMIT 1";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            object result = this.databaseContext.Slave.ExecuteScalar(sql, parameters);
            return result != null;
        }

        public PageTemplateEntity GetPageTemplate(string pageCode)
        {
            string sql = string.Concat(QUERY, " WHERE A.PageCode=?PageCode AND A.IsUsed=1 LIMIT 1");
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageCode", pageCode, DbType.AnsiString, size: 50);
            return this.databaseContext.Slave.QueryEntity<PageTemplateEntity>(sql, parameters);
        }

        public IEnumerable<PageTemplateEntity> GetSubPageTemplateList(string parentPageCode)
        {
            string sql = string.Concat(QUERY, " WHERE A.ParentPageCode=?ParentPageCode;");
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?ParentPageCode", parentPageCode, DbType.AnsiString, size: 50);
            return this.databaseContext.Slave.Query<PageTemplateEntity>(sql, parameters);
        }

        public IEnumerable<PageTemplateEntity> GetShowNavigationSubPageTemplateList(string pageCode)
        {
            string sql = string.Concat(QUERY, " WHERE A.NavigationShow=1 AND A.ParentPageCode=?PageCode;");
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageCode", pageCode, DbType.AnsiString, size: 50);
            return this.databaseContext.Slave.Query<PageTemplateEntity>(sql, parameters);
        }

        public void Delete(long pageTemplateId)
        {
            string sql = @"DELETE FROM PageTemplate WHERE PageTemplateId=?PageTemplateId;";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageTemplateId", pageTemplateId, DbType.Int64, size: 20);
            this.databaseContext.Master.Execute(sql, parameters, databaseContext.Transaction);
        }

        public IEnumerable<PageTemplateEntity> GetList(long websiteTemplateId)
        {
            string sql = string.Concat(QUERY, " WHERE A.WebsiteTemplateId=?WebsiteTemplateId;");
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 20);
            return this.databaseContext.Slave.Query<PageTemplateEntity>(sql, parameters);
        }

        public async Task<IEnumerable<PageTemplateEntity>> GetPageTemplateChildren(int websiteTemplateId, string parentPageCode)
        {
            string sql = string.Concat(QUERY_CHILDREN_COUNT, " WHERE A.WebsiteTemplateId=?WebsiteTemplateId");
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?WebsiteTemplateId", websiteTemplateId, DbType.Int32, size: 11);
            if (!string.IsNullOrWhiteSpace(parentPageCode))
            {
                sql = string.Concat(sql, " AND A.ParentPageCode=?ParentPageCode");
                parameters.Add("?ParentPageCode", parentPageCode, DbType.AnsiString, size: 50);
            }


            return await this.databaseContext.Slave.QueryAsync<PageTemplateEntity>(sql, parameters);
        }
        
        public IEnumerable<PageTemplateEntity> GetTree()
        {
            string sql = string.Format("{0} WHERE A.IsUsed=1", QUERY);
            return this.databaseContext.Slave.Query<PageTemplateEntity>(sql);
        }

        public int MaxLevel ()
        {
            string sql = @"SELECT MAX(PageLevel) FROM pagetemplate";
            return this.databaseContext.Slave.QueryEntity<int>(sql);
        }

        public IEnumerable<PageTemplateEntity> GetAllChild(string pageCode)
        {
            string querySql = @"SELECT
	                    A.PageTemplateId,
	                    A.PageName,
	                    A.PageCode,
	                    A.WebsiteTemplateId,
	                    A.IsUsed,
	                    A.ParentPageCode,
	                    A.PageLevel,
                        A.IsContentPage,
                        A.IsPagingListPage,
                        A.PagingListServiceTag,
                        A.ListSize,
                        A.PagingListServiceParams
                    FROM PageTemplate A
                    LEFT JOIN PageTemplate B ON A.ParentPageCode=B.PageCode
                    WHERE B.PageCode=?PageCode AND B.WebsiteTemplateId=A.WebsiteTemplateId";

            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageCode", pageCode, DbType.AnsiString, size: 50);
            return this.databaseContext.Slave.Query<PageTemplateEntity>(querySql, parameters);
        }

        public string GetParentAllPagePath(string pageCode)
        {
            string sql = @"SELECT GROUP_CONCAT(PageUrlName Separator '/') AS PageUrlName
                        FROM PageTemplate 
                        WHERE FIND_IN_SET(PageCode,(SELECT PageLevelCode FROM pagetemplate WHERE PageCode=?PageCode))";
            DynamicParameters parameters = new DynamicParameters();
            parameters.Add("?PageCode", pageCode, DbType.AnsiString, size: 50);
            return this.databaseContext.Slave.ExecuteScalar<string>(sql, parameters);
        }
    }
}
